#include "factory.h"

int exit_fds[2];

void exit_func(int signum)
{
    write(exit_fds[1], &signum, 1);
}

int main(int argc, char **argv)
{
    // if (argc != 5) 
    // {
    //     printf("./thread_pool_server IP PORT THRAED_NUM CAPACITY");
    //     return -1;
    // }

    char tcp_ip[20] = "192.168.149.128";
    char tcp_port[20] = "2000";
    char thread_num_str[20] = "5";
    char thread_capacity[20] = "20";

    pipe(exit_fds);

    if (fork()) // 主进程
    {
        close(exit_fds[0]);
        signal(SIGUSR1, exit_func); // SIGUSR1：10号信号
        wait(NULL);
        return 0;
    }
    close(exit_fds[1]);

    Factory_t f; // 主数据结构
    int thread_num = atoi(thread_num_str);
    int capacity = atoi(thread_capacity);
    factory_init(&f, thread_num, capacity);
    factory_start(&f, thread_num);


    int socket_fd;
    tcp_init(&socket_fd, tcp_ip, tcp_port);

    int epfd = epoll_create(1);
    struct epoll_event evs[2];
    epoll_add(epfd, socket_fd);
    epoll_add(epfd, exit_fds[0]);

    // 接收请求，加锁，放入队列，解锁，唤醒子线程
    int new_fd; // 客户端请求
    struct sockaddr_in client_addr; // 客户端信息结构体
    pQue_t pq = &f.que; // 客户队列
    pNode_t pnew;
    while (1)
    {
        int ready_fd_num = epoll_wait(epfd, evs, 2, -1);

        for (int i = 0; i < ready_fd_num; i ++)
        {
            if (evs[i].data.fd == new_fd) // 1. 有新客户端连接
            {
                bzero(&client_addr, sizeof(client_addr));
                socklen_t addr_len = sizeof(client_addr);
                new_fd = accept(socket_fd, (struct sockaddr *)&client_addr, &addr_len);
                printf("client %s %d connect success\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
                pnew = (pNode_t)malloc(sizeof(Node_t));
                pnew->new_fd = new_fd;
                pthread_mutex_lock(&pq->mutex);
                que_set(pq, pnew);
                pthread_mutex_unlock(&pq->mutex);
                pthread_cond_signal(&f.cond);
            }
            else if (evs[i].data.fd == exit_fds[0]) // 2. 接收到了退出信号
            {
                for (int j = 0; j < thread_num; j ++)
                {
                    pthread_cancel(f.pthid[j]);
                    printf("cancel success\n");
                    pthread_join(f.pthid[j], NULL);
                }
                exit(0);
            }
        }
    }

    return 0;
}